The following is your first chunk to start with. Remember, you can add chunks using the menu above (Insert -> R) or using the keyboard shortcut Ctrl+Alt+I. A good practice is to use different code chunks to answer different questions. You can delete this comment if you like.

Other useful keyboard shortcuts include Alt- for the assignment operator, and Ctrl+Shift+M for the pipe operator. You can delete these reminders if you don’t want them in your report.


Let’s first Load all the required libraries

#setwd("C:/GDrive/chingtea/BUDT758T2020/code/timeSeries/") #Don't forget to set your working directory before you start!

library("tidyverse")
library("fpp3")
── Attaching packages ────────────────────────────────────────────────────────────────────────────── fpp3 0.2 ──
✔ tsibble     0.8.6     ✔ feasts      0.1.3
✔ tsibbledata 0.1.0     ✔ fable       0.1.2
── Conflicts ───────────────────────────────────────────────────────────────────────────────── fpp3_conflicts ──
✖ fabletools::accuracy()   masks yardstick::accuracy()
✖ lubridate::date()        masks base::date()
✖ scales::discard()        masks purrr::discard()
✖ plotly::filter()         masks dplyr::filter(), stats::filter()
✖ fabletools::generate()   masks infer::generate()
✖ tsibble::id()            masks dplyr::id()
✖ tsibble::interval()      masks lubridate::interval()
✖ dplyr::lag()             masks stats::lag()
✖ caret::lift()            masks purrr::lift()
✖ fabletools::MAE()        masks caret::MAE()
✖ dials::margin()          masks ggplot2::margin()
✖ tsibble::new_interval()  masks lubridate::new_interval()
✖ fabletools::null_model() masks parsnip::null_model()
✖ fabletools::RMSE()       masks caret::RMSE()
library("plotly")
library("skimr")
library("lubridate")
tsDia <- read_csv('antidiabetic.csv')
Missing column names filled in: 'X1' [1]Parsed with column specification:
cols(
  X1 = col_double(),
  time = col_double(),
  value = col_double()
)

Read the data

month <- as_tibble(yearmonth(seq(as.Date("1991-07-01"), as.Date("2008-06-01"), by = "1 month"))) %>% 
  rename(month=value)


tsDia <- read_csv('antidiabetic.csv') %>%
  bind_cols(month) %>% 
  select(month, drugSales = value) %>%
  as_tsibble(index = month)
Missing column names filled in: 'X1' [1]Parsed with column specification:
cols(
  X1 = col_double(),
  time = col_double(),
  value = col_double()
)

Understanding time series data

Boston marathon

Trend without seasonality

tsBoston <-
  boston_marathon %>% 
  filter(Event == "Men's open division") %>%
  select(Year, Time) %>%
  as_tsibble()

Winning times at the Boston Marathon

plotBoston <-
  tsBoston %>% 
  autoplot() +
  xlab("Year (yearly data)") + ylab("Time in HH:MM:SS") +
  ggtitle("Winning times at the Boston Marathon (Men's open division)")
Plot variable not specified, automatically selected `.vars = Time`
ggplotly(plotBoston)

NA

Antidiabetic drug sales

Trend and seasonality are both evident

plotDia <-
  tsDia %>% 
  autoplot() +
  xlab("Year") + ylab("Total prescriptions ($ million)") +
  ggtitle("Antidiabetic drug sales") +
  scale_x_date(date_breaks = "years" , date_labels = "%y")
ggplotly(plotDia)

Antidiabetic drug decomposed

Seasonal plot for antidiabetic drug sales

plotDiaSeason <-
  tsDia %>%
  gg_season(drugSales, labels = "both") +
  xlab("Year") + ylab("Total prescriptions ($ million)") +
  ggtitle("Antidiabetic drug sales")
plotDiaSeason

U.S. gasoline supplied

Both trend and seasonality

tsGas <-us_gasoline

U.S. finished motor gasoline product supplied

plotGas <-
  tsGas %>% 
  autoplot() +
  xlab("Year (weekly data)") + ylab("Million barrels per week") +
  ggtitle("U.S. finished motor gasoline product supplied") +
  scale_x_date(date_breaks = "years" , date_labels = "%y")
ggplotly(plotGas)

U.S. gasoline supplied decomposed

plotGasDecomposed <- 
  tsGas %>%
  model(STL(Barrels ~ trend() + season(window='periodic'), robust = TRUE)) %>% 
  components() %>%
  autoplot() +
  xlab("Year (weekly data)") + ylab("Million barrels per week") +
  ggtitle("Seasonal and Trend decomposition using Loess (STL) for U.S. gasoline data") +
  scale_x_date(date_breaks = "years" , date_labels = "%y")
ggplotly(plotGasDecomposed)
plotGasDecomposed

U.S. retail employment Data

Trend overcomes seasonality

tsEmployment <-
  us_employment %>% 
  filter(Title == "Retail Trade", Month >= '1980-01-01') %>%
  select(Month, Employed)

U.S. retail employment

plotEmp <-
  tsEmployment %>% 
  autoplot() +
  xlab("Year (monthly data)") + ylab("Number of employed in retail (000)") +
  ggtitle("U.S. retail employment data")
ggplotly(plotEmp)

U.S. retail employment decomposed

plotEmpDecomposed <- 
  tsEmployment %>%
  model(STL(Employed ~ trend() + season(window='periodic'), robust = TRUE)) %>% 
  components() %>%
  autoplot() +
  xlab("Year (monthly data)") + ylab("Number of employed in retail (000)") +
  ggtitle("Seasonal and Trend decomposition using Loess (STL) for U.S. retail employment data") +
  scale_x_date(date_breaks = "years" , date_labels = "%y")
plotEmpDecomposed

U.S. personal consumption expenditure data

Both trend and seasonality are weak

tsEcon <- us_change %>% 
  filter(Quarter >= '1980-01-01') %>%
  select(Quarter, Consumption)

U.S. personal consumption

plotEcon <-
  tsEcon %>% 
  autoplot() +
  xlab("Year (quarterly data)") + ylab("Percentage changes in personal consumption") +
  ggtitle("U.S. personal consumption expenditure data") +
  scale_x_date(date_breaks = "years" , date_labels = "%y")
ggplotly(plotEcon)

U.S. consumption decomposed

plotEconDecomposed <- 
  tsEcon %>%
  model(STL(Consumption ~ trend() + season(window='periodic'), robust = TRUE)) %>% 
  components() %>%
  autoplot() +
  xlab("Year (quarterly data)") + ylab("Percentage changes in personal consumption") +
  ggtitle("Seasonal and Trend decomposition using Loess (STL) for U.S. consumption data") +
  scale_x_date(date_breaks = "years" , date_labels = "%y")
plotEconDecomposed

Accidental deaths in the U.S.

Sesonality without trend

tsAcc <-
  as_tsibble(USAccDeaths) %>% 
  rename(numOfAccDeaths = value)

Number of accidental deaths in the U.S.

plotAcc <-
  tsAcc %>% 
  autoplot() +
  xlab("Year") + ylab("Number of accidental deaths") +
  ggtitle("Number of accidental deaths in the U.S.") +
  scale_x_date(date_breaks = "years" , date_labels = "%y")
ggplotly(plotAcc)

Accidental deaths decomposed

plotAcc <- 
  tsAcc %>%
  model(STL(numOfAccDeaths ~ trend() + season(window='periodic'), robust = TRUE)) %>%
  components() %>%
  autoplot() +
  xlab("Year (monthly data)") + ylab("Number of accidental deaths") +
  ggtitle("Number of accidental deaths in the U.S.") +
  scale_x_date(date_breaks = "years" , date_labels = "%y")
plotAcc

Accidental deaths seasonal subseries

plotAccSub <- 
  tsAcc %>% 
  gg_subseries(numOfAccDeaths) +
  ylab("Number of accidental deaths") +
  xlab("Year (monthly data)") +
  ggtitle("Seasonal subseries plot: Number of accidental deaths in the U.S.")
plotAccSub

Preliminary analysis of time series data

Autocorrelation function plot for the antidiabetic drug sales data

plotDiaACF <-
  tsDia %>%
  ACF(drugSales, lag_max = 48) %>%
  autoplot() +  ggtitle("Autocorrelation function (ACF) plot for the antidiabetic drug sales data")
plotDiaACF

Lag plots for the accidental deaths data

plotAccLag <-
  tsAcc %>%
  gg_lag(numOfAccDeaths, geom='point') +
  xlab(NULL) + ylab(NULL) +
  ggtitle("Lag plots for the accidental deaths data")
ggplotly(plotAccLag)

NA

Autocorrelation function (ACF) plot for the accidental deaths data

plotAccACF <-
  tsAcc %>%
  ACF(numOfAccDeaths, lag_max = 9) %>%
  autoplot() +  ggtitle("Autocorrelation function (ACF) plot for the accidental deaths data")
plotAccACF

Noise(randomly generated)

set.seed(333)
y <- tsibble(sample = 1:100, Noise = rnorm(100), index = sample)
y %>%
  autoplot(Noise) + ggtitle("Noise over time") + xlab("Time")

Autocorrection for the noise

y %>%
  ACF(Noise) %>% autoplot()

Additive vs. multiplicative decomposition

Remember antidiabetic drug sales?

plotDia <-
  tsDia %>% 
  autoplot() +
  xlab("Year") + ylab("Total prescriptions ($ million)") +
  ggtitle("Antidiabetic drug sales") +
  scale_x_date(date_breaks = "years" , date_labels = "%y")
ggplotly(plotDia)

Additive decomposition

tsDia %>% 
  model(classical_decomposition(drugSales, type = "additive")) %>%
  components() %>%
  autoplot() +
  xlab("Year") + ylab("Total prescriptions ($ million)") +
  ggtitle("Classical additive decomposition of antidiabetic drug sales") +
  scale_x_date(date_breaks = "years" , date_labels = "%y")

Remember the STL decomposition?

plotDiaDecomposed <- 
  tsDia %>%
  model(STL(drugSales ~ trend(window=10) + season(window='periodic'), robust = TRUE)) %>% 
  components() %>%
  autoplot() +
  xlab("Year") + ylab("Total prescriptions ($ million)") +
  ggtitle("Seasonal and Trend decomposition using Loess (STL decomposition)") +
  scale_x_date(date_breaks = "years" , date_labels = "%y")
plotDiaDecomposed

Multiplicative decomposition

tsDia %>% 
  model(classical_decomposition(drugSales, type = "multiplicative")) %>%
  components() %>%
  autoplot() +
  xlab("Year") + ylab("Total prescriptions ($ million)") +
  ggtitle("Classical multiplicative decomposition of antidiabetic drug sales") +
  scale_x_date(date_breaks = "years" , date_labels = "%y")

Decompose data without seasonality(STL)

plotBostonDecomposed <-
  tsBoston %>%
  mutate(Seconds = as.numeric(Time, units="seconds")) %>%
  select(Year, Seconds) %>%
  model(STL(Seconds ~ trend(), robust = TRUE)) %>%
  components() %>%
  autoplot() +
  xlab("Year (yearly data)") + ylab("Time in seconds") +
  ggtitle("Winning times at the Boston Marathon (Men's open division)")
plotBostonDecomposed

Removing seasonal variation(STL)

U.S. retail employment data Seasonally Adjusted

plotEmpSeasonallyAdjusted <-
  tsEmployment %>%
  autoplot(Employed, color='#A9A9B0') +
  autolayer(components(tsEmployment %>% model(STL(Employed))), season_adjust, color='#1490D4') +
  xlab("Year (monthly data)") + ylab("Number of employed in retail (000)") +
  ggtitle("U.S. retail employment data")
ggplotly(plotEmpSeasonallyAdjusted)
us_employment %>%
  filter(Title %in% c('Construction', 'Manufacturing', 'Leisure and Hospitality')) %>% 
  as_tsibble(key=Title) %>%
  select(-Series_ID) %>% 
  features(Employed, feat_stl) %>% 
  rename_all(~str_remove(.x, '_year'))
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKICBwZGZfZG9jdW1lbnQ6CiAgICBsYXRleF9lbmdpbmU6IHhlbGF0ZXgKYWx3YXlzX2FsbG93X2h0bWw6IHllcwotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQoKIyBUaGlzIGNodW5rIHNob3dzL2hpZGVzIHRoZSBjb2RlIGluIHlvdXIgZmluYWwgcmVwb3J0LiBXaGVuIGVjaG8gPSBUUlVFLCB0aGUgY29kZQojIGlzIHNob3duIGluIHRoZSByZXBvcnQuIFdoZW4gZWNobyA9IEZBTFNFLCB0aGUgY29kZSBpcyBoaWRkZW4gZnJvbSB0aGUgZmluYWwgcmVwb3J0LgojIFdlIHdvdWxkIGxpa2UgdG8gc2VlIHlvdXIgY29kZSwgc28gcGxlYXNlIGxlYXZlIHRoZSBzZXR0aW5nIGFzIGlzIGR1cmluZyB0aGUgY291cnNlLgojIFRoaXMgY2h1bmsgd2lsbCBub3Qgc2hvdyB1cCBpbiB5b3VyIHJlcG9ydHMsIHNvIHlvdSBjYW4gc2FmZWx5IGlnbm9yZSBpdHMgZXhpc3RlbmNlLgoKa25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQoKYGBgCgoKVGhlIGZvbGxvd2luZyBpcyB5b3VyIGZpcnN0IGNodW5rIHRvIHN0YXJ0IHdpdGguIFJlbWVtYmVyLCB5b3UgY2FuIGFkZCBjaHVua3MgdXNpbmcgdGhlIG1lbnUKYWJvdmUgKEluc2VydCAtPiBSKSBvciB1c2luZyB0aGUga2V5Ym9hcmQgc2hvcnRjdXQgQ3RybCtBbHQrSS4gQSBnb29kIHByYWN0aWNlIGlzIHRvIHVzZQpkaWZmZXJlbnQgY29kZSBjaHVua3MgdG8gYW5zd2VyIGRpZmZlcmVudCBxdWVzdGlvbnMuIFlvdSBjYW4gZGVsZXRlIHRoaXMgY29tbWVudCBpZiB5b3UgbGlrZS4KCk90aGVyIHVzZWZ1bCBrZXlib2FyZCBzaG9ydGN1dHMgaW5jbHVkZSBBbHQtIGZvciB0aGUgYXNzaWdubWVudCBvcGVyYXRvciwgYW5kIEN0cmwrU2hpZnQrTQpmb3IgdGhlIHBpcGUgb3BlcmF0b3IuIFlvdSBjYW4gZGVsZXRlIHRoZXNlIHJlbWluZGVycyBpZiB5b3UgZG9uJ3Qgd2FudCB0aGVtIGluIHlvdXIgcmVwb3J0LgoKKioqCgpMZXQncyBmaXJzdCBMb2FkIGFsbCB0aGUgcmVxdWlyZWQgbGlicmFyaWVzCmBgYHtyfQojc2V0d2QoIkM6L0dEcml2ZS9jaGluZ3RlYS9CVURUNzU4VDIwMjAvY29kZS90aW1lU2VyaWVzLyIpICNEb24ndCBmb3JnZXQgdG8gc2V0IHlvdXIgd29ya2luZyBkaXJlY3RvcnkgYmVmb3JlIHlvdSBzdGFydCEKCmxpYnJhcnkoInRpZHl2ZXJzZSIpCmxpYnJhcnkoImZwcDMiKQpsaWJyYXJ5KCJwbG90bHkiKQpsaWJyYXJ5KCJza2ltciIpCmxpYnJhcnkoImx1YnJpZGF0ZSIpCgpgYGAKYGBge3J9CnRzRGlhIDwtIHJlYWRfY3N2KCdhbnRpZGlhYmV0aWMuY3N2JykKYGBgCgoKUmVhZCB0aGUgZGF0YQpgYGB7cn0KbW9udGggPC0gYXNfdGliYmxlKHllYXJtb250aChzZXEoYXMuRGF0ZSgiMTk5MS0wNy0wMSIpLCBhcy5EYXRlKCIyMDA4LTA2LTAxIiksIGJ5ID0gIjEgbW9udGgiKSkpICU+JSAKICByZW5hbWUobW9udGg9dmFsdWUpCgoKdHNEaWEgPC0gcmVhZF9jc3YoJ2FudGlkaWFiZXRpYy5jc3YnKSAlPiUKICBiaW5kX2NvbHMobW9udGgpICU+JSAKICBzZWxlY3QobW9udGgsIGRydWdTYWxlcyA9IHZhbHVlKSAlPiUKICBhc190c2liYmxlKGluZGV4ID0gbW9udGgpCgpgYGAKCioqKgojIyBVbmRlcnN0YW5kaW5nIHRpbWUgc2VyaWVzIGRhdGEKCiMjIyBCb3N0b24gbWFyYXRob24KIyMjIyBUcmVuZCB3aXRob3V0IHNlYXNvbmFsaXR5CmBgYHtyfQp0c0Jvc3RvbiA8LQogIGJvc3Rvbl9tYXJhdGhvbiAlPiUgCiAgZmlsdGVyKEV2ZW50ID09ICJNZW4ncyBvcGVuIGRpdmlzaW9uIikgJT4lCiAgc2VsZWN0KFllYXIsIFRpbWUpICU+JQogIGFzX3RzaWJibGUoKQoKYGBgCgojIyMgV2lubmluZyB0aW1lcyBhdCB0aGUgQm9zdG9uIE1hcmF0aG9uCmBgYHtyfQpwbG90Qm9zdG9uIDwtCiAgdHNCb3N0b24gJT4lIAogIGF1dG9wbG90KCkgKwogIHhsYWIoIlllYXIgKHllYXJseSBkYXRhKSIpICsgeWxhYigiVGltZSBpbiBISDpNTTpTUyIpICsKICBnZ3RpdGxlKCJXaW5uaW5nIHRpbWVzIGF0IHRoZSBCb3N0b24gTWFyYXRob24gKE1lbidzIG9wZW4gZGl2aXNpb24pIikKZ2dwbG90bHkocGxvdEJvc3RvbikKCmBgYAoKKioqCgojIyMgQW50aWRpYWJldGljIGRydWcgc2FsZXMKCiMjIyMgVHJlbmQgYW5kIHNlYXNvbmFsaXR5IGFyZSBib3RoIGV2aWRlbnQKYGBge3J9CnBsb3REaWEgPC0KICB0c0RpYSAlPiUgCiAgYXV0b3Bsb3QoKSArCiAgeGxhYigiWWVhciIpICsgeWxhYigiVG90YWwgcHJlc2NyaXB0aW9ucyAoJCBtaWxsaW9uKSIpICsKICBnZ3RpdGxlKCJBbnRpZGlhYmV0aWMgZHJ1ZyBzYWxlcyIpICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAieWVhcnMiICwgZGF0ZV9sYWJlbHMgPSAiJXkiKQpnZ3Bsb3RseShwbG90RGlhKQoKYGBgCgoKCiMjIyBBbnRpZGlhYmV0aWMgZHJ1ZyBkZWNvbXBvc2VkCmBgYHtyfQpwbG90RGlhRGVjb21wb3NlZCA8LSAKICB0c0RpYSAlPiUKICBtb2RlbChTVEwoZHJ1Z1NhbGVzIH4gdHJlbmQod2luZG93PTEwKSArIHNlYXNvbih3aW5kb3c9J3BlcmlvZGljJyksIHJvYnVzdCA9IFRSVUUpKSAlPiUgCiAgY29tcG9uZW50cygpICU+JQogIGF1dG9wbG90KCkgKwogIHhsYWIoIlllYXIiKSArIHlsYWIoIlRvdGFsIHByZXNjcmlwdGlvbnMgKCQgbWlsbGlvbikiKSArCiAgZ2d0aXRsZSgiU2Vhc29uYWwgYW5kIFRyZW5kIGRlY29tcG9zaXRpb24gdXNpbmcgTG9lc3MgKFNUTCBkZWNvbXBvc2l0aW9uKSIpICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAieWVhcnMiICwgZGF0ZV9sYWJlbHMgPSAiJXkiKQpnZ3Bsb3RseShwbG90RGlhRGVjb21wb3NlZCkKCmBgYAoKCiMjIyBTZWFzb25hbCBwbG90IGZvciBhbnRpZGlhYmV0aWMgZHJ1ZyBzYWxlcwpgYGB7cn0KcGxvdERpYVNlYXNvbiA8LQogIHRzRGlhICU+JQogIGdnX3NlYXNvbihkcnVnU2FsZXMsIGxhYmVscyA9ICJib3RoIikgKwogIHhsYWIoIlllYXIiKSArIHlsYWIoIlRvdGFsIHByZXNjcmlwdGlvbnMgKCQgbWlsbGlvbikiKSArCiAgZ2d0aXRsZSgiQW50aWRpYWJldGljIGRydWcgc2FsZXMiKQpwbG90RGlhU2Vhc29uCgpgYGAKCioqKgoKIyMjICBVLlMuIGdhc29saW5lIHN1cHBsaWVkCiMjIyMgQm90aCB0cmVuZCBhbmQgc2Vhc29uYWxpdHkKCmBgYHtyfQp0c0dhcyA8LXVzX2dhc29saW5lCgpgYGAKClUuUy4gZmluaXNoZWQgbW90b3IgZ2Fzb2xpbmUgcHJvZHVjdCBzdXBwbGllZApgYGB7cn0KcGxvdEdhcyA8LQogIHRzR2FzICU+JSAKICBhdXRvcGxvdCgpICsKICB4bGFiKCJZZWFyICh3ZWVrbHkgZGF0YSkiKSArIHlsYWIoIk1pbGxpb24gYmFycmVscyBwZXIgd2VlayIpICsKICBnZ3RpdGxlKCJVLlMuIGZpbmlzaGVkIG1vdG9yIGdhc29saW5lIHByb2R1Y3Qgc3VwcGxpZWQiKSArCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gInllYXJzIiAsIGRhdGVfbGFiZWxzID0gIiV5IikKZ2dwbG90bHkocGxvdEdhcykKCmBgYAoKIyMjIFUuUy4gZ2Fzb2xpbmUgc3VwcGxpZWQgZGVjb21wb3NlZApgYGB7cn0KcGxvdEdhc0RlY29tcG9zZWQgPC0gCiAgdHNHYXMgJT4lCiAgbW9kZWwoU1RMKEJhcnJlbHMgfiB0cmVuZCgpICsgc2Vhc29uKHdpbmRvdz0ncGVyaW9kaWMnKSwgcm9idXN0ID0gVFJVRSkpICU+JSAKICBjb21wb25lbnRzKCkgJT4lCiAgYXV0b3Bsb3QoKSArCiAgeGxhYigiWWVhciAod2Vla2x5IGRhdGEpIikgKyB5bGFiKCJNaWxsaW9uIGJhcnJlbHMgcGVyIHdlZWsiKSArCiAgZ2d0aXRsZSgiU2Vhc29uYWwgYW5kIFRyZW5kIGRlY29tcG9zaXRpb24gdXNpbmcgTG9lc3MgKFNUTCkgZm9yIFUuUy4gZ2Fzb2xpbmUgZGF0YSIpICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAieWVhcnMiICwgZGF0ZV9sYWJlbHMgPSAiJXkiKQpnZ3Bsb3RseShwbG90R2FzRGVjb21wb3NlZCkKcGxvdEdhc0RlY29tcG9zZWQKYGBgCgoqKioKCiMjIyBVLlMuIHJldGFpbCBlbXBsb3ltZW50IERhdGEKIyMjIyBUcmVuZCBvdmVyY29tZXMgc2Vhc29uYWxpdHkKCmBgYHtyfQp0c0VtcGxveW1lbnQgPC0KICB1c19lbXBsb3ltZW50ICU+JSAKICBmaWx0ZXIoVGl0bGUgPT0gIlJldGFpbCBUcmFkZSIsIE1vbnRoID49ICcxOTgwLTAxLTAxJykgJT4lCiAgc2VsZWN0KE1vbnRoLCBFbXBsb3llZCkKCmBgYAoKIyMjIyBVLlMuIHJldGFpbCBlbXBsb3ltZW50CmBgYHtyfQpwbG90RW1wIDwtCiAgdHNFbXBsb3ltZW50ICU+JSAKICBhdXRvcGxvdCgpICsKICB4bGFiKCJZZWFyIChtb250aGx5IGRhdGEpIikgKyB5bGFiKCJOdW1iZXIgb2YgZW1wbG95ZWQgaW4gcmV0YWlsICgwMDApIikgKwogIGdndGl0bGUoIlUuUy4gcmV0YWlsIGVtcGxveW1lbnQgZGF0YSIpCmdncGxvdGx5KHBsb3RFbXApCgpgYGAKCgojIyMgVS5TLiByZXRhaWwgZW1wbG95bWVudCBkZWNvbXBvc2VkCmBgYHtyfQpwbG90RW1wRGVjb21wb3NlZCA8LSAKICB0c0VtcGxveW1lbnQgJT4lCiAgbW9kZWwoU1RMKEVtcGxveWVkIH4gdHJlbmQoKSArIHNlYXNvbih3aW5kb3c9J3BlcmlvZGljJyksIHJvYnVzdCA9IFRSVUUpKSAlPiUgCiAgY29tcG9uZW50cygpICU+JQogIGF1dG9wbG90KCkgKwogIHhsYWIoIlllYXIgKG1vbnRobHkgZGF0YSkiKSArIHlsYWIoIk51bWJlciBvZiBlbXBsb3llZCBpbiByZXRhaWwgKDAwMCkiKSArCiAgZ2d0aXRsZSgiU2Vhc29uYWwgYW5kIFRyZW5kIGRlY29tcG9zaXRpb24gdXNpbmcgTG9lc3MgKFNUTCkgZm9yIFUuUy4gcmV0YWlsIGVtcGxveW1lbnQgZGF0YSIpICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAieWVhcnMiICwgZGF0ZV9sYWJlbHMgPSAiJXkiKQpwbG90RW1wRGVjb21wb3NlZAoKYGBgCgoqKioKCiMjIyBVLlMuIHBlcnNvbmFsIGNvbnN1bXB0aW9uIGV4cGVuZGl0dXJlIGRhdGEKIyMjIyBCb3RoIHRyZW5kIGFuZCBzZWFzb25hbGl0eSBhcmUgd2VhawpgYGB7cn0KdHNFY29uIDwtIHVzX2NoYW5nZSAlPiUgCiAgZmlsdGVyKFF1YXJ0ZXIgPj0gJzE5ODAtMDEtMDEnKSAlPiUKICBzZWxlY3QoUXVhcnRlciwgQ29uc3VtcHRpb24pCgpgYGAKCiMjIyMgVS5TLiBwZXJzb25hbCBjb25zdW1wdGlvbgpgYGB7cn0KcGxvdEVjb24gPC0KICB0c0Vjb24gJT4lIAogIGF1dG9wbG90KCkgKwogIHhsYWIoIlllYXIgKHF1YXJ0ZXJseSBkYXRhKSIpICsgeWxhYigiUGVyY2VudGFnZSBjaGFuZ2VzIGluIHBlcnNvbmFsIGNvbnN1bXB0aW9uIikgKwogIGdndGl0bGUoIlUuUy4gcGVyc29uYWwgY29uc3VtcHRpb24gZXhwZW5kaXR1cmUgZGF0YSIpICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAieWVhcnMiICwgZGF0ZV9sYWJlbHMgPSAiJXkiKQpnZ3Bsb3RseShwbG90RWNvbikKCmBgYAoKIyMjIyBVLlMuIGNvbnN1bXB0aW9uIGRlY29tcG9zZWQKYGBge3J9CnBsb3RFY29uRGVjb21wb3NlZCA8LSAKICB0c0Vjb24gJT4lCiAgbW9kZWwoU1RMKENvbnN1bXB0aW9uIH4gdHJlbmQoKSArIHNlYXNvbih3aW5kb3c9J3BlcmlvZGljJyksIHJvYnVzdCA9IFRSVUUpKSAlPiUgCiAgY29tcG9uZW50cygpICU+JQogIGF1dG9wbG90KCkgKwogIHhsYWIoIlllYXIgKHF1YXJ0ZXJseSBkYXRhKSIpICsgeWxhYigiUGVyY2VudGFnZSBjaGFuZ2VzIGluIHBlcnNvbmFsIGNvbnN1bXB0aW9uIikgKwogIGdndGl0bGUoIlNlYXNvbmFsIGFuZCBUcmVuZCBkZWNvbXBvc2l0aW9uIHVzaW5nIExvZXNzIChTVEwpIGZvciBVLlMuIGNvbnN1bXB0aW9uIGRhdGEiKSArCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gInllYXJzIiAsIGRhdGVfbGFiZWxzID0gIiV5IikKcGxvdEVjb25EZWNvbXBvc2VkCgpgYGAKCioqKgoKIyMjIEFjY2lkZW50YWwgZGVhdGhzIGluIHRoZSBVLlMuCiMjIyMgU2Vzb25hbGl0eSB3aXRob3V0IHRyZW5kCmBgYHtyfQp0c0FjYyA8LQogIGFzX3RzaWJibGUoVVNBY2NEZWF0aHMpICU+JSAKICByZW5hbWUobnVtT2ZBY2NEZWF0aHMgPSB2YWx1ZSkKCmBgYAoKTnVtYmVyIG9mIGFjY2lkZW50YWwgZGVhdGhzIGluIHRoZSBVLlMuCmBgYHtyfQpwbG90QWNjIDwtCiAgdHNBY2MgJT4lIAogIGF1dG9wbG90KCkgKwogIHhsYWIoIlllYXIiKSArIHlsYWIoIk51bWJlciBvZiBhY2NpZGVudGFsIGRlYXRocyIpICsKICBnZ3RpdGxlKCJOdW1iZXIgb2YgYWNjaWRlbnRhbCBkZWF0aHMgaW4gdGhlIFUuUy4iKSArCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gInllYXJzIiAsIGRhdGVfbGFiZWxzID0gIiV5IikKZ2dwbG90bHkocGxvdEFjYykKCmBgYAoKIyMjIyBBY2NpZGVudGFsIGRlYXRocyBkZWNvbXBvc2VkCmBgYHtyfQpwbG90QWNjIDwtIAogIHRzQWNjICU+JQogIG1vZGVsKFNUTChudW1PZkFjY0RlYXRocyB+IHRyZW5kKCkgKyBzZWFzb24od2luZG93PSdwZXJpb2RpYycpLCByb2J1c3QgPSBUUlVFKSkgJT4lCiAgY29tcG9uZW50cygpICU+JQogIGF1dG9wbG90KCkgKwogIHhsYWIoIlllYXIgKG1vbnRobHkgZGF0YSkiKSArIHlsYWIoIk51bWJlciBvZiBhY2NpZGVudGFsIGRlYXRocyIpICsKICBnZ3RpdGxlKCJOdW1iZXIgb2YgYWNjaWRlbnRhbCBkZWF0aHMgaW4gdGhlIFUuUy4iKSArCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gInllYXJzIiAsIGRhdGVfbGFiZWxzID0gIiV5IikKcGxvdEFjYwoKYGBgCgojIyMgQWNjaWRlbnRhbCBkZWF0aHMgc2Vhc29uYWwgc3Vic2VyaWVzCmBgYHtyfQpwbG90QWNjU3ViIDwtIAogIHRzQWNjICU+JSAKICBnZ19zdWJzZXJpZXMobnVtT2ZBY2NEZWF0aHMpICsKICB5bGFiKCJOdW1iZXIgb2YgYWNjaWRlbnRhbCBkZWF0aHMiKSArCiAgeGxhYigiWWVhciAobW9udGhseSBkYXRhKSIpICsKICBnZ3RpdGxlKCJTZWFzb25hbCBzdWJzZXJpZXMgcGxvdDogTnVtYmVyIG9mIGFjY2lkZW50YWwgZGVhdGhzIGluIHRoZSBVLlMuIikKcGxvdEFjY1N1YgoKYGBgCgoqKioKIyMgUHJlbGltaW5hcnkgYW5hbHlzaXMgb2YgdGltZSBzZXJpZXMgZGF0YQoKIyMjIyBBdXRvY29ycmVsYXRpb24gZnVuY3Rpb24gcGxvdCBmb3IgdGhlIGFudGlkaWFiZXRpYyBkcnVnIHNhbGVzIGRhdGEKYGBge3J9CnBsb3REaWFBQ0YgPC0KICB0c0RpYSAlPiUKICBBQ0YoZHJ1Z1NhbGVzLCBsYWdfbWF4ID0gNDgpICU+JQogIGF1dG9wbG90KCkgKyAgZ2d0aXRsZSgiQXV0b2NvcnJlbGF0aW9uIGZ1bmN0aW9uIChBQ0YpIHBsb3QgZm9yIHRoZSBhbnRpZGlhYmV0aWMgZHJ1ZyBzYWxlcyBkYXRhIikKcGxvdERpYUFDRgoKYGBgCgojIyMgTGFnIHBsb3RzIGZvciB0aGUgYWNjaWRlbnRhbCBkZWF0aHMgZGF0YQpgYGB7cn0KcGxvdEFjY0xhZyA8LQogIHRzQWNjICU+JQogIGdnX2xhZyhudW1PZkFjY0RlYXRocywgZ2VvbT0ncG9pbnQnKSArCiAgeGxhYihOVUxMKSArIHlsYWIoTlVMTCkgKwogIGdndGl0bGUoIkxhZyBwbG90cyBmb3IgdGhlIGFjY2lkZW50YWwgZGVhdGhzIGRhdGEiKQpnZ3Bsb3RseShwbG90QWNjTGFnKQoKYGBgCgojIyMgQXV0b2NvcnJlbGF0aW9uIGZ1bmN0aW9uIChBQ0YpIHBsb3QgZm9yIHRoZSBhY2NpZGVudGFsIGRlYXRocyBkYXRhCmBgYHtyfQpwbG90QWNjQUNGIDwtCiAgdHNBY2MgJT4lCiAgQUNGKG51bU9mQWNjRGVhdGhzLCBsYWdfbWF4ID0gOSkgJT4lCiAgYXV0b3Bsb3QoKSArICBnZ3RpdGxlKCJBdXRvY29ycmVsYXRpb24gZnVuY3Rpb24gKEFDRikgcGxvdCBmb3IgdGhlIGFjY2lkZW50YWwgZGVhdGhzIGRhdGEiKQpwbG90QWNjQUNGCgpgYGAKCgoKIyMjIE5vaXNlKHJhbmRvbWx5IGdlbmVyYXRlZCkKYGBge3J9CnNldC5zZWVkKDMzMykKeSA8LSB0c2liYmxlKHNhbXBsZSA9IDE6MTAwLCBOb2lzZSA9IHJub3JtKDEwMCksIGluZGV4ID0gc2FtcGxlKQp5ICU+JQogIGF1dG9wbG90KE5vaXNlKSArIGdndGl0bGUoIk5vaXNlIG92ZXIgdGltZSIpICsgeGxhYigiVGltZSIpCgpgYGAKCiMjIyBBdXRvY29ycmVjdGlvbiBmb3IgdGhlIG5vaXNlCmBgYHtyfQp5ICU+JQogIEFDRihOb2lzZSkgJT4lIGF1dG9wbG90KCkKCmBgYAoKIyMjIEFkZGl0aXZlIHZzLiBtdWx0aXBsaWNhdGl2ZSBkZWNvbXBvc2l0aW9uCiMjIyBSZW1lbWJlciBhbnRpZGlhYmV0aWMgZHJ1ZyBzYWxlcz8KYGBge3J9CnBsb3REaWEgPC0KICB0c0RpYSAlPiUgCiAgYXV0b3Bsb3QoKSArCiAgeGxhYigiWWVhciIpICsgeWxhYigiVG90YWwgcHJlc2NyaXB0aW9ucyAoJCBtaWxsaW9uKSIpICsKICBnZ3RpdGxlKCJBbnRpZGlhYmV0aWMgZHJ1ZyBzYWxlcyIpICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAieWVhcnMiICwgZGF0ZV9sYWJlbHMgPSAiJXkiKQpnZ3Bsb3RseShwbG90RGlhKQoKYGBgCgojIyMgQWRkaXRpdmUgZGVjb21wb3NpdGlvbgpgYGB7cn0KdHNEaWEgJT4lIAogIG1vZGVsKGNsYXNzaWNhbF9kZWNvbXBvc2l0aW9uKGRydWdTYWxlcywgdHlwZSA9ICJhZGRpdGl2ZSIpKSAlPiUKICBjb21wb25lbnRzKCkgJT4lCiAgYXV0b3Bsb3QoKSArCiAgeGxhYigiWWVhciIpICsgeWxhYigiVG90YWwgcHJlc2NyaXB0aW9ucyAoJCBtaWxsaW9uKSIpICsKICBnZ3RpdGxlKCJDbGFzc2ljYWwgYWRkaXRpdmUgZGVjb21wb3NpdGlvbiBvZiBhbnRpZGlhYmV0aWMgZHJ1ZyBzYWxlcyIpICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAieWVhcnMiICwgZGF0ZV9sYWJlbHMgPSAiJXkiKQoKYGBgCgojIyMgUmVtZW1iZXIgdGhlIFNUTCBkZWNvbXBvc2l0aW9uPwpgYGB7cn0KcGxvdERpYURlY29tcG9zZWQgPC0gCiAgdHNEaWEgJT4lCiAgbW9kZWwoU1RMKGRydWdTYWxlcyB+IHRyZW5kKHdpbmRvdz0xMCkgKyBzZWFzb24od2luZG93PSdwZXJpb2RpYycpLCByb2J1c3QgPSBUUlVFKSkgJT4lIAogIGNvbXBvbmVudHMoKSAlPiUKICBhdXRvcGxvdCgpICsKICB4bGFiKCJZZWFyIikgKyB5bGFiKCJUb3RhbCBwcmVzY3JpcHRpb25zICgkIG1pbGxpb24pIikgKwogIGdndGl0bGUoIlNlYXNvbmFsIGFuZCBUcmVuZCBkZWNvbXBvc2l0aW9uIHVzaW5nIExvZXNzIChTVEwgZGVjb21wb3NpdGlvbikiKSArCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gInllYXJzIiAsIGRhdGVfbGFiZWxzID0gIiV5IikKcGxvdERpYURlY29tcG9zZWQKCmBgYAoKIyMjIE11bHRpcGxpY2F0aXZlIGRlY29tcG9zaXRpb24KYGBge3J9CnRzRGlhICU+JSAKICBtb2RlbChjbGFzc2ljYWxfZGVjb21wb3NpdGlvbihkcnVnU2FsZXMsIHR5cGUgPSAibXVsdGlwbGljYXRpdmUiKSkgJT4lCiAgY29tcG9uZW50cygpICU+JQogIGF1dG9wbG90KCkgKwogIHhsYWIoIlllYXIiKSArIHlsYWIoIlRvdGFsIHByZXNjcmlwdGlvbnMgKCQgbWlsbGlvbikiKSArCiAgZ2d0aXRsZSgiQ2xhc3NpY2FsIG11bHRpcGxpY2F0aXZlIGRlY29tcG9zaXRpb24gb2YgYW50aWRpYWJldGljIGRydWcgc2FsZXMiKSArCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gInllYXJzIiAsIGRhdGVfbGFiZWxzID0gIiV5IikKCmBgYAoKKioqCgojIyMgRGVjb21wb3NlIGRhdGEgd2l0aG91dCBzZWFzb25hbGl0eShTVEwpCmBgYHtyfQpwbG90Qm9zdG9uRGVjb21wb3NlZCA8LQogIHRzQm9zdG9uICU+JQogIG11dGF0ZShTZWNvbmRzID0gYXMubnVtZXJpYyhUaW1lLCB1bml0cz0ic2Vjb25kcyIpKSAlPiUKICBzZWxlY3QoWWVhciwgU2Vjb25kcykgJT4lCiAgbW9kZWwoU1RMKFNlY29uZHMgfiB0cmVuZCgpLCByb2J1c3QgPSBUUlVFKSkgJT4lCiAgY29tcG9uZW50cygpICU+JQogIGF1dG9wbG90KCkgKwogIHhsYWIoIlllYXIgKHllYXJseSBkYXRhKSIpICsgeWxhYigiVGltZSBpbiBzZWNvbmRzIikgKwogIGdndGl0bGUoIldpbm5pbmcgdGltZXMgYXQgdGhlIEJvc3RvbiBNYXJhdGhvbiAoTWVuJ3Mgb3BlbiBkaXZpc2lvbikiKQpwbG90Qm9zdG9uRGVjb21wb3NlZAoKYGBgCgojIyMgUmVtb3Zpbmcgc2Vhc29uYWwgdmFyaWF0aW9uKFNUTCkKIyMjIFUuUy4gcmV0YWlsIGVtcGxveW1lbnQgZGF0YSBTZWFzb25hbGx5IEFkanVzdGVkCmBgYHtyfQpwbG90RW1wU2Vhc29uYWxseUFkanVzdGVkIDwtCiAgdHNFbXBsb3ltZW50ICU+JQogIGF1dG9wbG90KEVtcGxveWVkLCBjb2xvcj0nI0E5QTlCMCcpICsKICBhdXRvbGF5ZXIoY29tcG9uZW50cyh0c0VtcGxveW1lbnQgJT4lIG1vZGVsKFNUTChFbXBsb3llZCkpKSwgc2Vhc29uX2FkanVzdCwgY29sb3I9JyMxNDkwRDQnKSArCiAgeGxhYigiWWVhciAobW9udGhseSBkYXRhKSIpICsgeWxhYigiTnVtYmVyIG9mIGVtcGxveWVkIGluIHJldGFpbCAoMDAwKSIpICsKICBnZ3RpdGxlKCJVLlMuIHJldGFpbCBlbXBsb3ltZW50IGRhdGEiKQpnZ3Bsb3RseShwbG90RW1wU2Vhc29uYWxseUFkanVzdGVkKQoKYGBgCgpgYGB7cn0KdXNfZW1wbG95bWVudCAlPiUKICBmaWx0ZXIoVGl0bGUgJWluJSBjKCdDb25zdHJ1Y3Rpb24nLCAnTWFudWZhY3R1cmluZycsICdMZWlzdXJlIGFuZCBIb3NwaXRhbGl0eScpKSAlPiUgCiAgYXNfdHNpYmJsZShrZXk9VGl0bGUpICU+JQogIHNlbGVjdCgtU2VyaWVzX0lEKSAlPiUgCiAgZmVhdHVyZXMoRW1wbG95ZWQsIGZlYXRfc3RsKSAlPiUgCiAgcmVuYW1lX2FsbCh+c3RyX3JlbW92ZSgueCwgJ195ZWFyJykpCgpgYGAKCg==